home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Online / opennap / join.c < prev    next >
C/C++ Source or Header  |  2001-06-08  |  18KB  |  686 lines

  1. /* Copyright (C) 2000-1 drscholl@users.sourceforge.net
  2.    This is free software distributed under the terms of the
  3.    GNU Public License.  See the file COPYING for details.
  4.  
  5.    $Id: join.c,v 1.85 2001/02/15 08:39:45 drscholl Exp $ */
  6.  
  7. #ifndef WIN32
  8. #include <unistd.h>
  9. #endif
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include "opennap.h"
  14. #include "debug.h"
  15.  
  16. /* ensure the channel name contains only valid characters */
  17. int
  18. invalid_channel (const char *s)
  19. {
  20.     int     count = 0;
  21.  
  22.     if (option (ON_IRC_CHANNELS) && *s != '#' && *s != '&')
  23.     return 1;        /* must start with # or & */
  24.     s++;
  25.     while (*s)
  26.     {
  27.     if (*s < '!' || *s > '~' || strchr ("%$*?\",", *s))
  28.         return 1;
  29.     count++;
  30.     s++;
  31.     }
  32.     return ((count == 0)
  33.         || (Max_Channel_Length > 0 && count > Max_Channel_Length));
  34. }
  35.  
  36. static BAN *
  37. is_banned (LIST * bans, const char *nick, const char *host)
  38. {
  39.     char    mask[256];
  40.  
  41.     snprintf (mask, sizeof (mask), "%s!%s", nick, host);
  42.     for (; bans; bans = bans->next)
  43.     {
  44.     if (glob_match (((BAN *) bans->data)->target, mask))
  45.         return bans->data;
  46.     }
  47.     return 0;
  48. }
  49.  
  50. /* this function gets called when we see a JOIN from a remote server that
  51.  * shouldn't have happened, such as a channel full, +INVITE or a ban.  we
  52.  * need to send back a KICK to make sure all servers stay synched.
  53.  */
  54. static void
  55. join_desync (CONNECTION * con, const char *chan, USER * user,
  56.          const char *reason)
  57. {
  58.     log ("join_desync: server %s is desynced", con->host);
  59.     send_cmd (con, MSG_CLIENT_KICK, ":%s %s %s \"%s\"",
  60.           Server_Name, chan, user->nick, reason);
  61. }
  62.  
  63. /* handle client request to join channel */
  64. /* [ :<nick> ] <channel> */
  65. HANDLER (join)
  66. {
  67.     USER   *user;
  68.     CHANNEL *chan;
  69.     LIST   *list;
  70.     CHANUSER *chanUser, *cu;
  71.     int     chanop = 0;
  72.     int     local = 0;
  73.     char    chanbuf[256];    /* needed when creating a rollover channel */
  74.     char   *chan_name;
  75.     char   *sender_name;
  76.  
  77.     (void) tag;
  78.     (void) len;
  79.     ASSERT (validate_connection (con));
  80.     if (pop_user_server (con, tag, &pkt, &sender_name, &user) != 0)
  81.     return;
  82.     ASSERT (validate_user (user));
  83.     chan_name = next_arg (&pkt);
  84.     if (!chan_name)
  85.     {
  86.     unparsable (con);
  87.     return;
  88.     }
  89.  
  90.     /* this loop is here in case the channel has a limit so we can create
  91.        the rollover channels */
  92.     ASSERT (sizeof (chanbuf) >= (unsigned int) Max_Channel_Length);
  93.     chanbuf[sizeof (chanbuf) - 1] = 0;
  94.  
  95.     /* automatically prepend # to channel names if missing */
  96.     if (option (ON_IRC_CHANNELS) && *chan_name != '#' && *chan_name != '&')
  97.     {
  98.     if (ISUSER (con))
  99.     {
  100.         /* for older clients that still let channels through with no
  101.          * prefix, automatically prepend it here.  most clients seem to
  102.          * be able to deal with the join for a different channel being
  103.          * set back to them
  104.          */
  105.         snprintf (chanbuf, sizeof (chanbuf), "#%s", chan_name);
  106.         chan_name = chanbuf;
  107.     }
  108.     else
  109.     {
  110.         /* peer server shouldn't have let this through, so we will
  111.          * reject it.
  112.          */
  113.         join_desync (con, chan_name, user, "invalid channel name");
  114.         return;
  115.     }
  116.     }
  117.  
  118.     /* check if this is a local channel */
  119.     local = (*chan_name == '&');
  120.     if (local && ISSERVER (con))
  121.     {
  122.     log ("join: server %s joined local channel %s",
  123.          user->nick, user->server, chan_name);
  124.     return;
  125.     }
  126.  
  127.     if (user->level < LEVEL_MODERATOR)
  128.     {
  129.     /* enforce a maximum channels per user */
  130.     /* TODO: if linked servers have different settings, the channel
  131.        membership could become desynched */
  132.     if (list_count (user->channels) >= Max_User_Channels)
  133.     {
  134.         if (ISUSER (con))
  135.         send_cmd (con, MSG_SERVER_NOSUCH,
  136.               "channel join failed: you may only join %d channels",
  137.               Max_User_Channels);
  138.         else
  139.         join_desync (con, chan_name, user, "joined max channels");
  140.         return;
  141.     }
  142.     if (user->muzzled)
  143.     {
  144.         if (ISUSER (con))
  145.         send_cmd (con, MSG_SERVER_NOSUCH,
  146.               "channel join failed: can't join channels while muzzled");
  147.         else
  148.         join_desync (con, chan_name, user, "user is muzzled");
  149.         return;
  150.     }
  151.     }
  152.  
  153.     for (;;)
  154.     {
  155.     chan = hash_lookup (Channels, chan_name);
  156.     if (!chan)
  157.     {
  158.         /* check if this server allows normals to create channels */
  159.         if ((Server_Flags & ON_STRICT_CHANNELS) &&
  160.         user->level < LEVEL_MODERATOR)
  161.         {
  162.         if (ISUSER (con))
  163.             send_cmd (con, MSG_SERVER_NOSUCH,
  164.                   "channel join failed: permission denied");
  165.         else
  166.             join_desync (con, chan_name, user,
  167.                  "can't create channels");
  168.         return;
  169.         }
  170.         if (invalid_channel (chan_name))
  171.         {
  172.         if (ISUSER (con))
  173.             send_cmd (con, MSG_SERVER_NOSUCH,
  174.                   "channel join failed: invalid channel");
  175.         else
  176.             join_desync (con, chan_name, user,
  177.                  "invalid channel name");
  178.         return;
  179.         }
  180.         chan = new_channel ();
  181.         if (!chan)
  182.         return;        /* out of memory */
  183. #if DEBUG
  184.         chan->magic = MAGIC_CHANNEL;
  185. #endif
  186.         chan->name = STRDUP (chan_name);
  187.         if (!chan->name)
  188.         {
  189.         OUTOFMEMORY ("join");
  190.         FREE (chan);
  191.         return;
  192.         }
  193.  
  194.         chan->local = local;
  195.         chan->level = LEVEL_USER;
  196.  
  197. #if LOG_CHANNEL
  198.         if (local && !strcasecmp ("&LOG", chan->name))
  199.         {
  200.         chan->flags |= ON_CHANNEL_QUIET;
  201.         chan->level = LEVEL_ADMIN;
  202.         }
  203. #endif
  204.  
  205.         /* we only set the timestamp if a local user creates the
  206.          * channel.  otherwise we have to get it from the remote
  207.          * server since our clocks might not be synched.
  208.          */
  209.         if (ISUSER (con))
  210.         chan->timestamp = global.current_time;
  211.  
  212.         /* set the default topic */
  213.         snprintf (Buf, sizeof (Buf), "Welcome to the %s channel.",
  214.               chan->name);
  215.         chan->topic = STRDUP (Buf);
  216.         if (!chan->topic)
  217.         {
  218.         OUTOFMEMORY ("join");
  219.         FREE (chan->name);
  220.         FREE (chan);
  221.         return;
  222.         }
  223.         hash_add (Channels, chan->name, chan);
  224.         log ("join: creating channel %s", chan->name);
  225.  
  226.         if (ISUSER (con))
  227.         {
  228.         /* the first user to enter a channel gets ops.  note that
  229.          * predefined channels with no users never give out ops.
  230.          * this is to prevent people from trying to get ops by
  231.          * riding splits.  we also only set chanop when a local
  232.          * user creates the channel.  this is to avoid problems when
  233.          * syncing servers since the first join message we get is
  234.          * not necessarily the first person who entered the channel
  235.          * on the remote side.  we let the remote server tell us
  236.          * who is opped.
  237.          */
  238.         chanop = 1;
  239.         }
  240.     }
  241.     /* ensure that this user isn't already on this channel */
  242.     else if (list_find (user->channels, chan))
  243.     {
  244.         if (ISUSER (con))
  245.         send_cmd (con, MSG_SERVER_NOSUCH,
  246.               "channel join failed: already joined channel");
  247.         /* no need to correct desync since we already have the user in
  248.          * the channel.
  249.          */
  250.         return;
  251.     }
  252.     /* check to make sure the user has privilege to join */
  253.     else if (user->level < chan->level)
  254.     {
  255.         if (ISUSER (con))
  256.         send_cmd (con, MSG_SERVER_NOSUCH,
  257.               "channel join failed: requires level %s",
  258.               Levels[chan->level]);
  259.         else
  260.         join_desync (con, chan->name, user, "not required level");
  261.         return;
  262.     }
  263.     else
  264.     {
  265.         /* if not mod+, check extra permissions */
  266.         if (user->level < LEVEL_MODERATOR)
  267.         {
  268.         BAN    *ban;
  269.  
  270.         /* check to make sure this user is not banned from the channel */
  271.         if (
  272.             (ban =
  273.              is_banned (chan->bans, user->nick, my_ntoa (BSWAP32 (user->ip)))))
  274.         {
  275.             if (ISUSER (user->con))
  276.             {
  277.             send_cmd (user->con, MSG_SERVER_NOSUCH,
  278.                   "channel join failed: banned: %s",
  279.                   NONULL (ban->reason));
  280.             }
  281.             else
  282.             join_desync (con, chan->name, user,
  283.                      "banned from channel");
  284.             return;
  285.         }
  286.  
  287.         /* check for invitation */
  288.         if ((chan->flags & ON_CHANNEL_INVITE) &&
  289.             !list_find (chan->invited, user))
  290.         {
  291.             if (ISUSER (con))
  292.             send_cmd (con, MSG_SERVER_NOSUCH,
  293.                   "channel join failed: invite only");
  294.             else
  295.             join_desync (con, chan->name, user, "no invite");
  296.             return;
  297.         }
  298.  
  299.         if (chan->limit > 0
  300.             && list_count (chan->users) >= chan->limit)
  301.         {
  302.             if ((chan->flags & ON_CHANNEL_REGISTERED) == 0)
  303.             {
  304.             /* don't create rollover channels for non-registered
  305.              * channels.
  306.              */
  307.             if (ISUSER (con))
  308.                 send_cmd (con, MSG_SERVER_NOSUCH,
  309.                       "channel join failed: channel full");
  310.             else
  311.                 join_desync (con, chan->name, user,
  312.                      "channel full");
  313.             return;
  314.             }
  315.             /* for predefined channels, automatically create a rollover
  316.                channel when full */
  317.             else
  318.             {
  319.             char   *p;
  320.             int     n = 1;
  321.  
  322.             if (chan_name != chanbuf)
  323.             {
  324.                 strncpy (chanbuf, chan_name,
  325.                      sizeof (chanbuf) - 1);
  326.                 chan_name = chanbuf;
  327.             }
  328.             p = chanbuf + strlen (chanbuf);
  329. #define ISDIGIT(c) ((c)>=0 && (c)<='9')
  330.             while (p > chanbuf && ISDIGIT (*(p - 1)))
  331.                 p--;
  332.             if (ISDIGIT (*p))
  333.             {
  334.                 n = atoi (p);
  335.                 *p = 0;
  336.             }
  337.             snprintf (chanbuf + strlen (chanbuf),
  338.                   sizeof (chanbuf) - strlen (chanbuf), "%d",
  339.                   n + 1);
  340.             log ("join: trying channel %s", chanbuf);
  341.             continue;
  342.             }
  343.         }
  344.         }
  345.     }
  346.     break;
  347.     }
  348.  
  349.     ASSERT (validate_channel (chan));
  350.  
  351.     /* clean up invite lists - do this even when not +INVITE just in case
  352.      * it was present and then the channel was set to -INVITE
  353.      */
  354.     if (chan->invited)
  355.     chan->invited = list_delete (chan->invited, user);
  356.  
  357.     /* add this channel to the list of this user is subscribed to */
  358.     list = MALLOC (sizeof (LIST));
  359.     if (!list)
  360.     {
  361.     OUTOFMEMORY ("join");
  362.     goto error;
  363.     }
  364.     list->data = chan;
  365.     list->next = user->channels;
  366.     user->channels = list;
  367.  
  368.     /* add this user to the channel members list */
  369.     chanUser = CALLOC (1, sizeof (CHANUSER));
  370. #if DEBUG
  371.     chanUser->magic = MAGIC_CHANUSER;
  372. #endif
  373.     chanUser->user = user;
  374.  
  375.     list = MALLOC (sizeof (LIST));
  376.     if (!list)
  377.     {
  378.     OUTOFMEMORY ("join");
  379.     goto error;
  380.     }
  381.     list->data = chanUser;
  382.     list->next = chan->users;
  383.     chan->users = list;
  384.  
  385.     /* if there are linked servers, send this message along */
  386.     if (!chan->local)
  387.     pass_message_args (con, tag, ":%s %s", user->nick, chan->name);
  388.  
  389.     /* if local user send an ack for the join */
  390.     if (ISUSER (con))
  391.     {
  392.     /* notify client of success */
  393.     send_cmd (con, MSG_SERVER_JOIN_ACK, "%s", chan->name);
  394.  
  395.     if ((chan->flags & ON_CHANNEL_QUIET) == 0)
  396.     {
  397.         /* send the client the list of current users in the channel */
  398.         for (list = chan->users; list; list = list->next)
  399.         {
  400.         cu = list->data;
  401.         ASSERT (cu != 0);
  402.         ASSERT (cu->magic == MAGIC_CHANUSER);
  403.         if (!cu->user->cloaked || user->level >= LEVEL_MODERATOR)
  404.             send_cmd (con, MSG_SERVER_CHANNEL_USER_LIST /* 408 */ ,
  405.                   "%s %s %d %d", chan->name, cu->user->nick,
  406.                   cu->user->shared, cu->user->speed);
  407.         }
  408.     }
  409.     }
  410.  
  411.     if ((chan->flags & ON_CHANNEL_QUIET) == 0)
  412.     {
  413.     /* notify members of the channel that this user has joined */
  414.     for (list = chan->users; list; list = list->next)
  415.     {
  416.         cu = list->data;
  417.         ASSERT (cu != 0);
  418.         ASSERT (cu->magic == MAGIC_CHANUSER);
  419.         if (ISUSER (cu->user->con) && cu->user != user &&
  420.         (!user->cloaked || cu->user->level >= LEVEL_MODERATOR))
  421.         send_cmd (cu->user->con, MSG_SERVER_JOIN, "%s %s %d %d",
  422.               chan->name, user->nick, user->shared, user->speed);
  423.     }
  424.     }
  425.  
  426.     /* notify ops/mods+ of this users status */
  427.     if (chanop)
  428.     {
  429.     notify_ops (chan, "Server %s set %s as operator on channel %s",
  430.             Server_Name, user->nick, chan->name);
  431.     /* set the flag after the notice so the user isn't notified
  432.      * twice.
  433.      */
  434.     chanUser->flags |= ON_CHANNEL_OPERATOR;
  435.     /* broadcast op message to all servers.  this should *only* happen
  436.      * when a local user creates a new channel.  the reason we do this
  437.      * is to solve the problem of server linking when the first join
  438.      * message we get is not necessarily a channel op.  so we rely on
  439.      * the remote server to tell us which users are opped.
  440.      */
  441.     ASSERT (ISUSER (con));
  442.     if (!chan->local)
  443.         pass_message_args (NULL, MSG_CLIENT_OP, ":%s %s %s :%u",
  444.                    Server_Name, chan->name, user->nick,
  445.                    chan->timestamp);
  446.     }
  447.  
  448.     if (ISUSER (con))
  449.     {
  450.     if ((chan->flags & ON_CHANNEL_QUIET) == 0)
  451.     {
  452.         /* send end of channel list message */
  453.         /* NOTE: for some reason this is the way the napster.com servers send
  454.            the messages.  I'm not sure why they send the end of channel list
  455.            AFTER the join message for yourself */
  456.         send_cmd (con, MSG_SERVER_CHANNEL_USER_LIST_END /*409 */ , "%s",
  457.               chan->name);
  458.     }
  459.  
  460.     /* send channel topic */
  461.     ASSERT (chan->topic != 0);
  462.     send_cmd (con, MSG_SERVER_TOPIC /*410 */ , "%s %s", chan->name,
  463.           chan->topic);
  464.     if (chanop)
  465.         send_cmd (con, MSG_SERVER_NOSUCH,
  466.               "Server %s set you as operator on channel %s",
  467.               Server_Name, chan->name);
  468.     }
  469.     return;
  470.  
  471.   error:
  472.     /* set things back to a sane state */
  473.     chan->users = list_delete (chan->users, user);
  474.     user->channels = list_delete (user->channels, chan);
  475.     if (!chan->users)
  476.     {
  477.     log ("join: destroying channel %s", chan->name);
  478.     hash_remove (Channels, chan->name);
  479.     }
  480.     return;
  481. }
  482.  
  483. /* 823 [ :<sender> ] <channel> [level [timestamp]]
  484.  * queries/sets the minimum user level required to enter a channel
  485.  */
  486. HANDLER (channel_level)
  487. {
  488.     int     level;
  489.     char   *sender;
  490.     USER   *senderUser;
  491.     int     ac = -1;
  492.     char   *av[3];
  493.     CHANNEL *chan;
  494.     int     desync = 0;
  495.  
  496.     (void) tag;
  497.     (void) len;
  498.     ASSERT (validate_connection (con));
  499.  
  500.     if (pop_user_server (con, tag, &pkt, &sender, &senderUser))
  501.     return;
  502.  
  503.     if (pkt)
  504.     ac = split_line (av, sizeof (av) / sizeof (char), pkt);
  505.  
  506.     if (ac < 1)
  507.     {
  508.     print_args (ac, av);
  509.     unparsable (con);
  510.     return;
  511.     }
  512.     chan = hash_lookup (Channels, av[0]);
  513.     if (!chan)
  514.     {
  515.     nosuchchannel (con);
  516.     return;
  517.     }
  518.     ASSERT (validate_channel);
  519.  
  520.     if (ac == 1)
  521.     {
  522.     /* query the current mode */
  523.     CHECK_USER_CLASS ("channel_level");
  524.     send_cmd (con, MSG_SERVER_NOSUCH, "Channel %s is level %s",
  525.           chan->name, Levels[chan->level]);
  526.     return;
  527.     }
  528.  
  529.     level = get_level (av[1]);
  530.     if (level == -1)
  531.     {
  532.     if (ISUSER (con))
  533.         send_cmd (con, MSG_SERVER_NOSUCH,
  534.               "channel level failed: invalid level");
  535.     return;
  536.     }
  537.     if (chan->level == level)
  538.     return;            /* same value, ignore */
  539.  
  540.     if (ISSERVER (con) && chan->local)
  541.     {
  542.     log ("channel_level: server %s accessed local channel %s",
  543.          con->host, chan->name);
  544.     return;
  545.     }
  546.  
  547.     /* check for permission */
  548.     if (senderUser && senderUser->level < LEVEL_MODERATOR
  549.     && !is_chanop (chan, senderUser))
  550.     {
  551.     if (ISUSER (con))
  552.     {
  553.         send_cmd (con, MSG_SERVER_NOSUCH,
  554.               "channel level failed: you are not channel operator");
  555.         return;
  556.     }
  557.     desync = 1;
  558.     }
  559.     /* check the TS if present */
  560.     else if (ISSERVER (con) && ac > 2)
  561.     {
  562.     time_t  ts = atoi (av[2]);
  563.  
  564.     if (chan->timestamp > 0 && (ts == 0 || ts > chan->timestamp))
  565.         desync = 1;
  566.     else
  567.         chan->timestamp = ts;
  568.     }
  569.  
  570.     if (desync)
  571.     {
  572.     /* detected server desync, correct the mode on the remote server */
  573.     log ("channel_level: server %s is desynced", con->host);
  574.     send_cmd (con, tag, ":%s %s %s %u",
  575.           Server_Name, chan->name, Levels[chan->level],
  576.           chan->timestamp);
  577.     return;
  578.     }
  579.  
  580.     if (!chan->local)
  581.     pass_message_args (con, tag, ":%s %s %s %u",
  582.                sender, chan->name, Levels[level],
  583.                chan->timestamp);
  584.     chan->level = level;
  585.     notify_ops (chan, "%s set channel %s to level %s",
  586.         sender, chan->name, Levels[level]);
  587. }
  588.  
  589. /* 826 [:sender] <channel> [limit [timestamp]]
  590.  * queries/sets the max number of users on a channel
  591.  */
  592. HANDLER (channel_limit)
  593. {
  594.     int     ac = -1;
  595.     int     limit;
  596.     int     desync = 0;
  597.     char   *av[3];
  598.     char   *sender;
  599.     USER   *senderUser;
  600.     CHANNEL *chan;
  601.  
  602.     ASSERT (validate_connection (con));
  603.     (void) len;
  604.     if (pop_user_server (con, tag, &pkt, &sender, &senderUser))
  605.     return;
  606.     if (pkt)
  607.     ac = split_line (av, FIELDS (av), pkt);
  608.     if (ac < 1)
  609.     {
  610.     unparsable (con);
  611.     return;
  612.     }
  613.     chan = hash_lookup (Channels, av[0]);
  614.     if (!chan)
  615.     {
  616.     nosuchchannel (con);
  617.     return;
  618.     }
  619.     if (ac == 1)
  620.     {
  621.     /*query current limit */
  622.     CHECK_USER_CLASS ("channel_limit");
  623.     send_cmd (con, MSG_SERVER_NOSUCH, "Channel %s has limit %d",
  624.           chan->name, chan->limit);
  625.     return;
  626.     }
  627.     if (ISSERVER (con) && chan->local)
  628.     {
  629.     log ("channel_limit: server %s accessed local channel %s",
  630.          con->host, chan->name);
  631.     return;
  632.     }
  633.     limit = atoi (av[1]);
  634.     if (limit < 0 || limit > 65535)
  635.     {
  636.     if (ISUSER (con))
  637.         send_cmd (con, MSG_SERVER_NOSUCH,
  638.               "channel limit failed: invalid limit");
  639.     return;
  640.     }
  641.     if (senderUser && senderUser->level < LEVEL_MODERATOR
  642.     && !is_chanop (chan, senderUser))
  643.     {
  644.     if (ISUSER (con))
  645.     {
  646.         send_cmd (con, MSG_SERVER_NOSUCH,
  647.               "channel limit failed: you are not channel operator");
  648.         return;
  649.     }
  650.     desync = 1;
  651.     }
  652.     /* check timestamp */
  653.     else if (ISSERVER (con) && ac > 2)
  654.     {
  655.     time_t  ts = atoi (av[2]);
  656.  
  657.     if (chan->timestamp > 0 && (ts == 0 || ts > chan->timestamp))
  658.         desync = 1;
  659.     else
  660.         chan->timestamp = ts;
  661.     }
  662.  
  663.     if (desync)
  664.     {
  665.     /* server is out of sync, reset its limit */
  666.     log ("channel_limit: server %s is desynced", con->host);
  667.     send_cmd (con, tag, ":%s %s %d %u",
  668.           Server_Name, chan->name, chan->limit, chan->timestamp);
  669.     return;
  670.     }
  671.  
  672.     /* wait until now to check for this so that if a remote server has
  673.      * a different timestamp we can sync that even if the value is the
  674.      * same
  675.      */
  676.     if (chan->limit == limit)
  677.     return;            /* same value, just ignore it */
  678.  
  679.     chan->limit = limit;
  680.     if (!chan->local)
  681.     pass_message_args (con, tag, ":%s %s %d %u", sender, chan->name,
  682.                limit, chan->timestamp);
  683.     notify_ops (chan, "%s set limit on channel %s to %d", sender, chan->name,
  684.         limit);
  685. }
  686.